package legumes.client.ui.basket.slate;

import legumes.client.resources.PNResources;
import legumes.client.services.callbacks.SaveStallCallback;
import legumes.client.services.util.rpc.RPCCallSequencer;
import legumes.client.ui.widgets.form.item.PriceFloatItem;
import legumes.client.ui.widgets.form.item.ProductNameAutoSuggestComboItem;
import legumes.client.ui.widgets.form.item.QuantityFloatItem;
import legumes.client.ui.widgets.form.item.QuantityUnitFormItemFactory;
import legumes.client.ui.widgets.utils.Formatters;
import legumes.shared.domain.OnSaleProduct;
import legumes.shared.domain.Price;
import legumes.shared.domain.Product;
import legumes.shared.domain.Quantity;
import legumes.shared.domain.Stall;
import legumes.shared.domain.Unit;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FlexTable;
import com.smartgwt.client.core.Function;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.WidgetCanvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.events.CloseClientEvent;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.CellClickEvent;
import com.smartgwt.client.widgets.grid.events.CellClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;

public class ProductMarketEditionWindow extends Window {

	private final static String ID_DIV_PRODUCT_IMG = "ProductMarketEditionWindowDivProductImgID";
	private final static String ID_NEW_PRODUCT = "newItem";
	
	private static final float NEW_PRODUCT_DEFAULT_QUANTITY = 1f;
	private static final Unit NEW_PRODUCT_DEFAULT_QUANTITY_UNIT = Unit.KG;
	
	private String productNameImgDivLastClassName = "";
	private String productVarietyImgDivLastClassName = "";
	private String productCategoryImgDivLastClassName = "";
	
	private Element elDivProductImg = null;
	private FlexTable flexTableOutsideBasket;
	private OnSaleProduct onSaleProduct;
	private ButtonItem biDel;
	private ButtonItem biValidate;
	
	private ProductNameAutoSuggestComboItem fiProductName;
	private PriceFloatItem fiSalePrice;
	private QuantityFloatItem fiSaleQuantity;
	private FormItem fiSaleQuantityUnit;
	private Function onDataOnServerChanged;
	private Stall stall;
	private boolean editBasketProduct = true;
	private DynamicForm form;
	
	
	public ProductMarketEditionWindow(Stall stall_, OnSaleProduct onSaleProduct_, 
			Function onDataOnServerChanged_, boolean editBasketProduct_) {
		super();
		editBasketProduct = editBasketProduct_;
		onSaleProduct = onSaleProduct_;
		stall = stall_;
		onDataOnServerChanged = onDataOnServerChanged_;
		setWidth(480);
		setHeight(200);
		String titleWindow = isANewProduct()?"Nouveau produit" : onSaleProduct.getProduct().getName();
		setTitle("<img src=\""
				+ PNResources.INSTANCE.shoppingChartIcon().getURL()
				+ "\" />&nbsp;" + titleWindow);

		setShowCloseButton(true);
		setShowMinimizeButton(false);
		setCanDrag(true);
		setCanDragReposition(true);
		setIsModal(true);
		setShowModalMask(true);  
		setAutoCenter(true);
		addCloseClickHandler(new CloseClickHandler() {  
            public void onCloseClick(CloseClientEvent event) {  
                destroy();  
            }  
        });  
		buildPanel();
		initData();
		show();
		if( (!editBasketProduct_) || isANewProduct()){
			fiProductName.focusInItem();
		} else {
			fiSalePrice.focusInItem();
		}
	}
	
	public ProductMarketEditionWindow(Stall stall_, OnSaleProduct product_, 
			Function onDataOnServerChanged_) {
		this(stall_, product_, onDataOnServerChanged_, false);
	}

	private boolean isANewProduct(){
		return (onSaleProduct==null || (onSaleProduct!=null && onSaleProduct.getId()==-1));
	}
	
	private void initData() {
		if(onSaleProduct != null && onSaleProduct.getId()!=-1){
			fiProductName.setValue( onSaleProduct.getProduct().getName() );
			fiSaleQuantityUnit.setValue( onSaleProduct.getPrice().getQuantity().getUnitAsEnum().getDisplayName()  );
			fiSaleQuantity.setValue( onSaleProduct.getPrice().getQuantity().getValue());
			fiSalePrice.setValue( onSaleProduct.getPrice().getAmount() );
		} else { 
			fiProductName.setValue( "" );
			fiSaleQuantityUnit.setValue( NEW_PRODUCT_DEFAULT_QUANTITY_UNIT.getDisplayName() );
			fiSaleQuantity.setValue( NEW_PRODUCT_DEFAULT_QUANTITY );
			fiSalePrice.setValue( 1.0f );
			biDel.setVisible(false);
			biValidate.setColSpan(2);
		}
	}

	private void buildPanel() {
		HLayout mainLayout = new HLayout();
		mainLayout.setMargin(10);
		
		mainLayout.setMembers( buildProductPanel(), buildFormPanel());
		
		addItem(mainLayout);
	}
	
	private Canvas buildFormPanel(){
		form = new DynamicForm();
		form.setPadding(5);  
		form.setWidth("*");
		form.setLayoutAlign(Alignment.CENTER);
		form.setNumCols(4);
		form.setValidateOnExit(true);
		
		fiProductName = new ProductNameAutoSuggestComboItem();
		fiProductName.setStartRow(true);
		fiProductName.setEndRow(true);
		if(onSaleProduct!=null){
			fiProductName.setSelectedProduct(onSaleProduct.getProduct());
		}
		fiProductName.addComboListClickHandler(new CellClickHandler() {
			
			@Override
			public void onCellClick(CellClickEvent event) {
				ListGridRecord r = event.getRecord();
				String productName = r.getAttribute("productName");

				boolean isANewProductSelected = r.getAttributeAsBoolean("isANewProduct");
				if(!isANewProductSelected){
					onProductNameChanged(productName);
				}
			}
		});
		fiProductName.addChangedHandler(new ChangedHandler() {
			
			@Override
			public void onChanged(ChangedEvent event) {
				checkHtmlElementInitialized();
				Object curProductNameObj = event.getValue();
				if(elDivProductImg != null && curProductNameObj != null){
					String name = curProductNameObj.toString();
					onProductNameChanged(name);
				}
			}
		});

		
		fiSalePrice = new PriceFloatItem();
		fiSalePrice.setVisible(!editBasketProduct);
		fiSalePrice.setStartRow(true);
		fiSalePrice.setEndRow(true);
		fiSalePrice.addChangeHandler(new ChangeHandler() {
			
			
			@Override
			public void onChange(ChangeEvent event) {
				checkHtmlElementInitialized();
				Object curPriceObj = event.getValue();
				if(elDivProductImg != null && curPriceObj != null){
					Element elt = DOM.getElementById("shoppingChartGreen.price." + getHTMLIdProduct() );
					if(elt!=null){
						String productPrice = Formatters.formatPrice(curPriceObj, true);
						elt.setInnerHTML( productPrice );
					}
				}
			}
		});

		fiSaleQuantity = new QuantityFloatItem();
		fiSaleQuantity.setStartRow(true);
		fiSaleQuantity.setEndRow(false);
		fiSaleQuantity.setType(ListGridFieldType.FLOAT.toString());
		fiSaleQuantity.addChangeHandler(new ChangeHandler() {
			
			
			@Override
			public void onChange(ChangeEvent event) {
				checkHtmlElementInitialized();
				Object curProductQteObj = event.getValue();
				if(elDivProductImg != null && curProductQteObj != null){
					Element elt = DOM.getElementById("shoppingChartGreen.quantity." + getHTMLIdProduct() );
					if(elt!=null){
						String appendSpacesToProductName = "";
						String productQuantity = Formatters.formatQuantity( curProductQteObj );
						if(productQuantity.length()<=8){
							appendSpacesToProductName = "    ";
						}
						elt.setInnerText( appendSpacesToProductName + productQuantity );
					}
				}
			}
		});
		
		Unit quantiteUnit = isANewProduct()?null:onSaleProduct.getPrice().getQuantity().getUnitAsEnum();
		fiSaleQuantityUnit = QuantityUnitFormItemFactory.createFormItem(quantiteUnit);
		fiSaleQuantityUnit.setShowTitle(false);
		fiSaleQuantityUnit.setStartRow(false);
		fiSaleQuantityUnit.setEndRow(true);
		fiSaleQuantityUnit.addChangeHandler(new ChangeHandler() {
			
			
			@Override
			public void onChange(ChangeEvent event) {
				checkHtmlElementInitialized();
				Object curProductQteObj = event.getValue();
				if(elDivProductImg != null && curProductQteObj != null){
					Element elt = DOM.getElementById("shoppingChartGreen.quantityunit." + getHTMLIdProduct() );
					if(elt!=null){
						String appendSpacesToProductName = "";
						String productQuantity = curProductQteObj.toString();
						if(productQuantity.length()<=8 && !fiSalePrice.getVisible() ){
							appendSpacesToProductName = "    ";
						}
						elt.setInnerText( appendSpacesToProductName + productQuantity );
					}
				}
			}
		});

    	biValidate = new ButtonItem("AddToBasket", "Valider");
    	biValidate.setAutoFit(true);
    	biValidate.setColSpan(1);
    	biValidate.setAlign(Alignment.CENTER);
    	biValidate.setStartRow(true);
    	biValidate.setEndRow(false);
    	biValidate.setIcon( PNResources.INSTANCE.addIcon().getURL() );
    	biValidate.addClickHandler( createClickhandler() );
    	
    	biDel = new ButtonItem("RemoveFromBasket", "Supprimer");
    	biDel.setColSpan(1);
    	biDel.setIcon( PNResources.INSTANCE.deleteIcon().getURL() );
    	biDel.setAlign(Alignment.CENTER);
    	biDel.setStartRow(false);
    	biDel.setEndRow(false);
    	biDel.addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if( onSaleProduct != null){
					stall.removeOnSaleProduct( onSaleProduct );
					saveOnServer();
				}
				ProductMarketEditionWindow.this.destroy();
			}
		});
    	
    	ButtonItem biCancel = new ButtonItem("CancelAddToBasket", "Annuler");
    	biCancel.setColSpan(2);
    	biCancel.setAutoFit(true);
    	biCancel.setAlign(Alignment.CENTER);
    	biCancel.setStartRow(true);
    	biCancel.setEndRow(false);
    	biCancel.setIcon( PNResources.INSTANCE.cancelIcon().getURL() );
    	biCancel.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				ProductMarketEditionWindow.this.destroy();
			}
		});
    	
    	form.setFields(fiProductName, fiSalePrice, fiSaleQuantity, fiSaleQuantityUnit, biValidate, biDel, biCancel);

        return form;
	}
	
	private String getHTMLIdProduct(){
		String idProductToResearch = ID_NEW_PRODUCT;
		if(!editBasketProduct && onSaleProduct != null){
			idProductToResearch = onSaleProduct.getProduct().getName();
		}
		return idProductToResearch;
	}
	
	private void onProductNameChanged(String pName_){
		checkHtmlElementInitialized();
		
	//	Object oldValue = event.getOldValue();
	//	if ( oldValue!=null){
	//		elDivProductImg.removeClassName( PNResources.PRODUCT_NAME_CSS_PREFIX + oldValue.toString().toLowerCase());
	//	}
		
		removeClasses();
		
		Element elt = DOM.getElementById( "shoppingChartGreen.txt." + getHTMLIdProduct() );
		if(elt!=null){
			String appendSpacesToProductName = "";
			if(pName_.length()<=8){
				appendSpacesToProductName = "    ";
			}
			elt.setInnerText( appendSpacesToProductName + pName_ );
		}
		
		String productClassName = pName_.toLowerCase();
		if( pName_.length()>=2){
			//ask if the product exists
			Product suggestedProduct = fiProductName.findSuggestionProduct(pName_);
			if(suggestedProduct!=null){
				String productVariety = suggestedProduct.getProductVariety().getName();
				String productCategory = suggestedProduct.getProductVariety().getProductCategory().getName();
				String productVarietyClassName = productVariety!=null?productVariety.toLowerCase():"";
				String productCategoryClassName = productCategory!=null?productCategory.toLowerCase():"";
				
				addClasses(productClassName, productVarietyClassName, productCategoryClassName);
			}
		}
	//		String productVariety = event.getItem().getAttribute("productVariety");
	//		String productCategory = event.getItem().getAttribute("productCategory");
	//		String productVarietyClassName = productVariety!=null?productVariety.toLowerCase():"";
	//		String productCategoryClassName = productCategory!=null?productCategory.toLowerCase():"";
	//		
	//		addClasses(productClassName, productVarietyClassName, productCategoryClassName);
	}
	private Canvas buildProductPanel(){
		flexTableOutsideBasket = new FlexTable();

		String productId = getHTMLIdProduct();
		String name = onSaleProduct==null?"":onSaleProduct.getProduct().getName();
		String quantity = Formatters.formatQuantity( new Float(onSaleProduct==null?NEW_PRODUCT_DEFAULT_QUANTITY:
			onSaleProduct.getPrice().getQuantity().getValue()) );
		
		String quantityUnit = onSaleProduct==null?NEW_PRODUCT_DEFAULT_QUANTITY_UNIT.getDisplayName():
				onSaleProduct.getPrice().getQuantity().getUnitAsEnum().getDisplayName();
		
		String appendSpacesToProductName = "";
		if(name.length()<=8){
			appendSpacesToProductName = "&nbsp;&nbsp;&nbsp;";
		}
		String priceTxt = "";
		String price = "";
		if(!editBasketProduct){
			price = Formatters.formatPrice(onSaleProduct.getPrice(), true);
			priceTxt = price + " / " + quantity + quantityUnit;
		}
		String appendSpacesToPriceTxt = "";
		if(priceTxt.length()<=16){
			appendSpacesToPriceTxt = "&nbsp;&nbsp;&nbsp;";
		}
		String priceHtml = "<span class=\"priceTxt\">" + appendSpacesToPriceTxt;
		if(!editBasketProduct){
			priceHtml +=   "<span id=\"shoppingChartGreen.price." + productId + "\">" + price + "</span> / ";
		}
		priceHtml += "<span id=\"shoppingChartGreen.quantity." + productId + "\">" + quantity + "</span>&nbsp;" +
					 "<span id=\"shoppingChartGreen.quantityunit." + productId + "\">" + quantityUnit + "</span>";
		priceHtml += "</span>";//Close span class priceTxt
		flexTableOutsideBasket.setHTML(0, 0,
				//"<div class=\"" + glueCagette + "\">" +
				"<div class=\"slate\">"
				+ "<span id=\"shoppingChartGreen." + productId + "\" class=\"productInChartGreenFlag \" /><BR/>"
				+ "<span id=\"shoppingChartGreen.txt." + productId + "\" class=\"slateTxt\">" + appendSpacesToProductName
				+ name + "</span><BR/>" 
				+ priceHtml + "</div>");
		flexTableOutsideBasket.setHTML(1, 0, 
				//"<div class=\"" + glueCagette + "\">" +
				"<div class=\"borderCagette\">" +								
				"<div id=\"" + ID_DIV_PRODUCT_IMG + "\" class=\"" + PNResources.PRODUCT_NAME_CSS_PREFIX + "commonVegetable " + PNResources.PRODUCT_NAME_CSS_PREFIX + name.toLowerCase() + "\">" +
				"</div></div></div>"
		);
		
		return new WidgetCanvas(flexTableOutsideBasket);
	}
	
	protected ClickHandler createClickhandler(){
		return new ClickHandler() {
			
        	
			@Override
			public void onClick(ClickEvent event) {
				if( form.validate() ){
					
					try{
						Product newProduct = fiProductName.getSelectedProduct();
						Float newPrice = null;
						if(! editBasketProduct){
							newPrice = Formatters.extractFloat( fiSalePrice.getValueAsString() );
						}
						Float newQuantite = fiSaleQuantity.getValueAsFloat();
						String newQuantiteUnit = (String)fiSaleQuantityUnit.getValue();
	//					String newCategorie = (String)newValues.get("adminBasketOutsideCat");
						
						String oldProductName = onSaleProduct==null?null:onSaleProduct.getProduct().getName();
						Float oldPrice = onSaleProduct==null?null:onSaleProduct.getPrice().getAmount();
						Float oldQuantite = onSaleProduct==null?null:onSaleProduct.getPrice().getQuantity().getValue();
						String oldQuantiteUnit = onSaleProduct==null?null:onSaleProduct.getPrice().getQuantity().getUnitAsEnum().getDisplayName();
	//					String oldCategorie = product==null?null:(String)oldValues.getAttribute("adminBasketOutsideCat");
						
						onValidateAction(newProduct, oldProductName,
								newPrice, oldPrice, 
								newQuantite, oldQuantite, newQuantiteUnit, oldQuantiteUnit);
	//					updateCat(onSaleProductToAdd.getProduct(), newCategorie, oldCategorie);
						
					} catch(Exception e_){
						GWT.log("Basket outside panel : onEditComplete ", e_);
					}
					ProductMarketEditionWindow.this.destroy();
				}
            }
		};
	}
	
	protected void onValidateAction(Product newProduct, String oldProductName,
			Float newPrice, Float oldPrice, 
			Float newQuantite, Float oldQuantite, String newQuantiteUnit, String oldQuantiteUnit){
		OnSaleProduct onSaleProductToAdd = updateProduct(stall, newProduct, oldProductName);
		updatePriceAndQuantity(onSaleProductToAdd, newPrice, oldPrice, 
				newQuantite, oldQuantite, newQuantiteUnit, oldQuantiteUnit);

		saveOnServer();
	}
	
	private void saveOnServer(){
		RPCCallSequencer callSequencer = new RPCCallSequencer("Enregistrement en cours...");
		final SaveStallCallback saveStallCallback = new SaveStallCallback(stall);
		callSequencer.addCall(saveStallCallback);
		callSequencer.addRunnable(new Runnable() {
			public void run() {
				if( onDataOnServerChanged != null){
					onDataOnServerChanged.execute();
				}
			}
		});
		callSequencer.callSequence();
	}
	
	
	
	
	
	
	
	
	
	
	

	private OnSaleProduct updateProduct(Stall stall_, Product newProduct_, String oldProductName_){
		OnSaleProduct onSaleProductToAdd = null;
		if( newProduct_ != null){
			onSaleProductToAdd = stall_.findOnSaleProduct(oldProductName_);
			if(onSaleProductToAdd==null){
				onSaleProductToAdd = new OnSaleProduct();
				onSaleProductToAdd.setId( stall_.getMenu().getDate() );
				stall_.getOnSaleProducts().add(onSaleProductToAdd);
			}
			
			Product p = onSaleProductToAdd.getProduct();
			if( newProduct_ != null && newProduct_.getName().trim().length()>0){
				if( onSaleProductToAdd.getProduct() != null ){
					p.setName(newProduct_.getName());
					p.setProductVariety(newProduct_.getProductVariety());
				} else {
					p = newProduct_;
					onSaleProductToAdd.setProduct(p);
				}
			}
		} else {
			onSaleProductToAdd = onSaleProduct;
		}
		return onSaleProductToAdd;
	}
	
	private Price createPrice(Float newProductPrice_, Float oldProductPrice_
	){
		Price price = new Price();
		if( newProductPrice_ == null && oldProductPrice_ != null){
			price.setAmount( oldProductPrice_ );
		} else if( newProductPrice_ != null ){
			price.setAmount( newProductPrice_ );
		} else {
			price.setAmount( 0f );
		}
		return price;
	}
	
	protected Quantity createQuantity(Float newQuantite_, Float oldQuantite_,
			String newQuantiteUnit_, String oldQuantiteUnit
	){
		Quantity q = new Quantity();
		if( newQuantite_ == null && oldQuantite_ != null){
			q.setValue( oldQuantite_ );
		} else if( newQuantite_ != null ){
			q.setValue( newQuantite_ );
		} else {
			q.setValue( 0f );
		}
		
		if( newQuantiteUnit_ == null && oldQuantiteUnit != null){
			q.setUnit( Unit.fromDisplayName(oldQuantiteUnit).name() );
		} else if( newQuantiteUnit_ != null ){
			q.setUnit( Unit.fromDisplayName(newQuantiteUnit_).name() );
		} else {
			q.setUnit( Unit.KG.name() );
		}
		
		return q;
	}
	
	private void updatePriceAndQuantity(OnSaleProduct onSaleProductToAdd_, 
			Float newProductPrice_, Float oldProductPrice_,
			Float newQuantite_, Float oldQuantite_,
			String newQuantiteUnit_, String oldQuantiteUnit_
	){
		Price price = createPrice(newProductPrice_, oldProductPrice_);
		price.setQuantity( createQuantity(newQuantite_, oldQuantite_, newQuantiteUnit_, oldQuantiteUnit_) );
		onSaleProductToAdd_.setPrice(price);
	}
	
	
	
	
	
	private void removeClasses(){
		//Product name
		if( productNameImgDivLastClassName!=null && productNameImgDivLastClassName.length()>0){
			elDivProductImg.removeClassName(PNResources.PRODUCT_CATEGORY_CSS_PREFIX +productNameImgDivLastClassName);
		}
		//Variety
		if( productVarietyImgDivLastClassName!=null && productVarietyImgDivLastClassName.length()>0){
			elDivProductImg.removeClassName(PNResources.PRODUCT_CATEGORY_CSS_PREFIX +productVarietyImgDivLastClassName);
		}
		//Category
		if( productCategoryImgDivLastClassName!=null && productCategoryImgDivLastClassName.length()>0){
			elDivProductImg.removeClassName(PNResources.PRODUCT_CATEGORY_CSS_PREFIX +productCategoryImgDivLastClassName);
		}
	}
	
	private void addClasses(String productClassName_, String productVarietyClassName_, String productCategoryClassName_){
		//Category
		if( productCategoryClassName_ != null && productCategoryClassName_.length()>0){
			elDivProductImg.addClassName(PNResources.PRODUCT_CATEGORY_CSS_PREFIX + productCategoryClassName_);
			productCategoryImgDivLastClassName = productCategoryClassName_;
		}
		//Variety
		if( productVarietyClassName_ != null && productVarietyClassName_.length()>0){
			elDivProductImg.addClassName(PNResources.PRODUCT_VARIETY_CSS_PREFIX + productVarietyClassName_);
			productVarietyImgDivLastClassName = productVarietyClassName_;
		}
		//Product
		if( productClassName_ != null && productClassName_.length()>0){
			elDivProductImg.addClassName(PNResources.PRODUCT_NAME_CSS_PREFIX + productClassName_);
			productNameImgDivLastClassName = productClassName_;
		}
	}
	
	private void checkHtmlElementInitialized(){
		if ( elDivProductImg == null ){
			elDivProductImg = DOM.getElementById( ID_DIV_PRODUCT_IMG );
		}
	}
	

	public Product getSelectedProduct(){
		return fiProductName.getSelectedProduct();
	}
}
